package com.lanxiao.cloud.modules.oauth.domain.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lanxiao.cloud.common.core.enums.DelFlagEnum;
import com.lanxiao.cloud.common.core.utils.StringUtils;
import com.lanxiao.cloud.common.mybatis.service.impl.BaseServiceImpl;
import com.lanxiao.cloud.modules.oauth.domain.check.CheckRoleHandle;
import com.lanxiao.cloud.modules.oauth.domain.event.PermissionChangEvent;
import com.lanxiao.cloud.modules.oauth.domain.event.PermissionChangEventPublisher;
import com.lanxiao.cloud.modules.oauth.domain.model.Role;
import com.lanxiao.cloud.modules.oauth.domain.model.RolePermission;
import com.lanxiao.cloud.modules.oauth.domain.model.UserRole;
import com.lanxiao.cloud.modules.oauth.domain.service.IRoleService;
import com.lanxiao.cloud.modules.oauth.infrastructure.repository.RoleMapper;
import com.lanxiao.cloud.modules.oauth.infrastructure.repository.RolePermissionMapper;
import com.lanxiao.cloud.modules.oauth.infrastructure.repository.UserRoleMapper;
import java.util.List;
import java.util.Objects;
import org.springframework.stereotype.Service;

/**
 * @author ：qiaoliang
 * @date ：2021-09-16
 */
@Service
public class RoleServiceImpl  extends
    BaseServiceImpl<Long, RoleMapper, Role> implements
    IRoleService {

  private final PermissionChangEventPublisher changEventPublisher;
  private final RolePermissionMapper rolePermissionMapper;
  private final UserRoleMapper userRoleMapper;

  public RoleServiceImpl(
      PermissionChangEventPublisher changEventPublisher,
      RolePermissionMapper rolePermissionMapper,
      UserRoleMapper userRoleMapper) {
    this.changEventPublisher = changEventPublisher;
    this.rolePermissionMapper = rolePermissionMapper;
    this.userRoleMapper = userRoleMapper;
  }

  @Override
  public void saveRole(Role role, List<Long> ids) {
    this.getRoleAndCheckRole(role.getId(), role.getMark());
    this.save(role);
    this.updateRoleAndPermission(role.getId(), ids);
    changEventPublisher.asyncPublish(new PermissionChangEvent());
  }

  @Override
  public void updateRole(Role role, List<Long> ids) {
    this.getRoleAndCheckRole(role.getId(), role.getMark());
    this.updateById(role);
    this.updateRoleAndPermission(role.getId(), ids);
    changEventPublisher.asyncPublish(new PermissionChangEvent());
  }

  @Override
  public void deleteRole(Long id) {
    final Role role = this.getRoleAndCheckExist(id);
    role.delete();
    rolePermissionMapper.delete(
        new LambdaQueryWrapper<RolePermission>().eq(RolePermission::getRoleId, id));
    this.updateById(role);
    changEventPublisher.asyncPublish(new PermissionChangEvent());
  }

  @Override
  public void updateRoleAndPermission(Long id, List<Long> permissionIds) {
    this.getRoleAndCheckExist(id);
    rolePermissionMapper.delete(
        new LambdaQueryWrapper<RolePermission>().eq(RolePermission::getRoleId, id));
    permissionIds.forEach(permissionId-> rolePermissionMapper.insert(new RolePermission(id, permissionId)));
  }

  @Override
  public void updateUserAndRole(Long id, List<Long> roleIds) {
    userRoleMapper.delete(
        new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, id));
    roleIds.forEach(roleId-> userRoleMapper.insert(new UserRole(id, roleId)));
  }

  private Role getRoleAndCheckExist(Long id) {
    final Role role = this.getById(id);
    CheckRoleHandle.init(role).checkExist().empty();
    return role;
  }

  private void getRoleAndCheckRole(Long id, String mark) {
    LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.notLike(Objects.nonNull(id), Role::getId, id)
        .eq(StringUtils.isNotBlank(mark), Role::getMark, mark)
        .notLike(Role::getDelFlag, DelFlagEnum.DELETE);
    CheckRoleHandle.init(this.getOne(queryWrapper))
        .checkRepeatMark(mark).empty();
  }

}
